package com.delu.controller;

import com.alibaba.fastjson.JSONObject;
import com.delu.data.Result;
import com.delu.dto.UserDTO;
import com.delu.dto.UsersDTO;
import com.delu.em.ResultEnum;
import com.delu.controller.ShiroMD5.ShiroUtils;
import com.delu.entity.User;
import com.delu.mapper.UserMapper;
import com.delu.service.UserService;
import com.delu.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("user")
@ResponseBody
@Api(value = "用户管理系统")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private ShiroUtils shiroUtils;
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @ApiOperation(value = "客户端登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "usrname", value = "用户名",required = true,paramType = "path"),
            @ApiImplicitParam(name = "password", value = "密码",required = true,paramType = "path")
    })
    @GetMapping
    public Result login(@RequestParam("usrname") String usrname,@RequestParam("password")String password){
        //获取用户输入账户密码生成token交给shiro判断
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(usrname,password);
        try{
            subject.login(token);
            //登陆成功后,修改用户的登录时间等
            userService.updateUserByUserName(usrname);
        }catch (UnknownAccountException uae){
            System.out.println("对用户【" + usrname +"】进行登录验证，验证未通过，未知账户！");
            return Result.response(ResultEnum.ERROEUSER).setData(0);
        }catch (AuthenticationException ae){
            System.out.println("对用户【" + usrname +"】进行登录验证，验证未通过，用户名、密码不正确！");
            return Result.response(ResultEnum.ERRORPWD).setData(1);
        }
        //单点登录
        User user =  userService.selectUserIdByUserName(usrname);
        //设置脱敏类
        UserDTO dto = new UserDTO();
        //将信息脱敏
        BeanUtils.copyProperties(user,dto);
        //使用 jwt
        //token1是jwt包装的对象,token是提交给shiro的
        String token1 = jwtUtil.createJwt(dto.getUserId().toString(), JSONObject.toJSONString(dto), "guest");

        return Result.response(ResultEnum.SUCCESS).setData(token1);
    }
    @ApiOperation(value = "客户端注册")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "User", value = "用户实体类",required = true,paramType = "body")
    })
    //密码注册
    @PostMapping
    public Result toregister(@RequestBody User user){
        //设置随机盐
        String salt = shiroUtils.generateSalt(6);
        user.setSalt(salt);
        String password = shiroUtils.encryptPassword("MD5", user.getPassword(), salt, 10);
        user.setPassword(password);
        //判断账户是否存在
        if (userService.selectByName(user.getUsrname())!=null){
            System.out.println("账号存在");
            User user1 = userService.selectByName(user.getUsrname());
            return Result.response(ResultEnum.OVERUNAME).setData(0);
        }else {
            userService.insertUser(user);
            //注册时增加优惠卷
            redisTemplate.boundValueOps(user.getUserId()).set(1);
            //设置优惠卷过期时间15天
            redisTemplate.expire(user.getUserId(),15, TimeUnit.DAYS);
            return Result.response(ResultEnum.SUCCESS).setData(1);
        }
    }
    //手机短信登录 And 注册
    @PostMapping("noteLogin")
    public Result noteLogin(String phoneNum,String code,int type){
        if (type == 1) {
            if (code == null){
                try {
                    //获取到用户的手机号,将手机号放到rocketmq中
                    rocketMQTemplate.convertAndSend("phoneNum", phoneNum);
                } catch (Exception e) {
                    e.printStackTrace();
                    return Result.response(ResultEnum.ERROR);
                }
            }
            if (code != null){
                //code 用户传入验证码 ,redisCode  redis保存的用户验证码
                String redisCode = (String) redisTemplate.boundValueOps(phoneNum).get();
                if (code.equals(redisCode)){
                    //单点登录,通过手机号查询用户信息,放入jwt封装
                    User user = userService.selectUserIdByUserPhoneNum(phoneNum);
                    //设置脱敏类
                    UserDTO dto = new UserDTO();
                    //将信息脱敏
                    BeanUtils.copyProperties(user, dto);
                    //使用 jwt
                    //token1是jwt包装的对象,token是提交给shiro的
                    String token1 = jwtUtil.createJwt(dto.getUserId().toString(), JSONObject.toJSONString(dto), "guest");
                    return Result.response(ResultEnum.SUCCESS).setData(token1);
                }else {
                    return Result.response(ResultEnum.ERROR).setData(2);
                }
            }
        }else if(type == 2){
            if (code == null){
                try {
                    //获取到用户的手机号,将手机号放到rocketmq中
                    rocketMQTemplate.convertAndSend("phoneNum", phoneNum);
                } catch (Exception e) {
                    e.printStackTrace();
                    return Result.response(ResultEnum.ERROR);
                }
            }
            if (code !=null){
                //code 用户传入验证码 ,redisCode  redis保存的用户验证码
                String redisCode = (String) redisTemplate.boundValueOps(phoneNum).get();
                if (code.equals(redisCode)){
                    User user = new User();
                    user.setUsrname(phoneNum);
                    //增加注册成功用户到表中
                    userService.insertUser(user);
                    //注册时增加优惠卷
                    redisTemplate.boundValueOps(user.getUserId()).set(1);
                    //设置优惠卷过期时间15天
                    redisTemplate.expire(user.getUserId(),15, TimeUnit.DAYS);
                }else {
                    return Result.response(ResultEnum.ERROR).setData(2);
                }
            }
        }

        return Result.response(ResultEnum.SUCCESS);
    }

    //实名认证
    @PostMapping("real")
    public Result RealNameCertification(@RequestBody User user, HttpServletRequest request){
        //根据用户登录获取到token值
        String strId = null;
        try {
            String authToken = request.getHeader("authToken");
            //使用jwt工具类解析token中存放的内容
            Claims claims = jwtUtil.parseJwt(authToken);
            //获取对象id
            strId = claims.getId();
            //获取存入的用户对象
            claims.getSubject();
            //将jwt封装的用户转成Long
            Long id = Long.valueOf(strId);
            //将用户id存入用户所输入的user对象,调用修改方法,完成通过id修改,达到"实名认证"的目的
            user.setUserId(id);
            //调用修改方法
            userService.updateUserByUserId(user);
        }catch (ExpiredJwtException e){

            return Result.response(ResultEnum.ERROR);
        }
        return Result.response(ResultEnum.SUCCESS).setData(strId);
    }
    //验证手机号是否存在
    @GetMapping("exist")
    public Result existPhoneNum(@RequestParam("phoneNum")String phoneNum){
        if (userService.selectPhoneNum(phoneNum)){
            return Result.response(ResultEnum.OVERUNAME);
        }else {
            return Result.response(ResultEnum.SUCCESS);
        }
    }

    @GetMapping("selectUserByVipId")
    @ApiOperation(value = "根据用户id查询")
    @ApiImplicitParam(name = "userId",value = "用户id",required = true,paramType = "query")
    public Result selectUserByVipId(@RequestParam("userId") Long userId) {
        try {
            UsersDTO usersDTO = new UsersDTO();
            User user = userMapper.selectById(userId);
            BeanUtils.copyProperties(user,usersDTO);
            return Result.response(ResultEnum.SUCCESS).setData(user);
        }catch (Exception e){
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }

    @PutMapping("updateUser")//@RequestParam java中的数据类型如string 加上此注解表名参数为必填项
    //@RequestBody  就收实体类要求前台必须用json的格式传参
    @ApiOperation(value = "用户实体类修改")
    @ApiImplicitParam(name = "userDTO",value = "用户实体类",required = true,paramType = "path")
    public Result updateUserById(@RequestBody UsersDTO usersDTO) {
        User user = new User();

        try {
             BeanUtils.copyProperties(usersDTO,user);
            userMapper.updateById(user);
            return Result.response(ResultEnum.SUCCESS).setData("ok");
        }catch (Exception e){
            e.printStackTrace();
            return Result.response(ResultEnum.ERROR).setData(e);
        }
    }
}
